﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Emico.Data.Repository;

namespace Emico.Data.Entity.Repository
{
    public static class DbRepositoryExtensions
    {
        #region LINQ

        #region All

        public static bool All<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().All(predicate);
        }

        public static bool Any<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().All(predicate);
        }

        #endregion

        #region Average

        public static decimal? Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static decimal Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static double? Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static double Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static float? Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static float Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static double? Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static double Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static double? Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        public static double Average<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Average(selector);
        }

        #endregion

        #region Contains

        public static bool Contains<TEntity>(this IDbRepository<TEntity> repository, TEntity item)
            where TEntity : class
        {
            return repository.AsQueryable().Contains(item);
        }

        #endregion

        #region Count

        public static int Count<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().Count(predicate);
        }

        #endregion

        #region First

        public static TEntity First<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().First();
        }

        public static TEntity First<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().First(predicate);
        }

        #endregion

        #region FirstOrDefault

        public static TEntity FirstOrDefault<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().FirstOrDefault();
        }

        public static TEntity FirstOrDefault<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().FirstOrDefault(predicate);
        }

        #endregion

        #region LongCount

        public static long LongCount<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().LongCount();
        }

        public static long LongCount<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().LongCount(predicate);
        }

        #endregion

        #region Max

        public static TEntity Max<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().Max();
        }

        public static TResult Max<TEntity, TResult>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TResult>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Max(selector);
        }

        #endregion

        #region Min

        public static TEntity Min<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().Min();
        }

        public static TResult Min<TEntity, TResult>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TResult>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Min(selector);
        }

        #endregion

        #region Signal

        public static TEntity Single<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().Single();
        }

        public static TEntity Single<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().Single(predicate);
        }

        #endregion

        #region SingleOrDefault

        public static TEntity SingleOrDefault<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().SingleOrDefault();
        }

        public static TEntity SingleOrDefault<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().SingleOrDefault(predicate);
        }

        #endregion

        #region Sum

        public static decimal? Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static decimal Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static double? Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static double Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static float? Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static float Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static int? Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static int Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static long? Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }

        public static long Sum<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().Sum(selector);
        }


        #endregion

        #region Take

        public static IQueryable<TEntity> Take<TEntity>(this IDbRepository<TEntity> repository, int count)
            where TEntity : class
        {
            return repository.AsQueryable().Take(count);
        }

        #endregion

        #region ToArray

        #endregion

        #region ToDictionary

        public static Dictionary<TKey, TEntity> ToDictionary<TEntity, TKey>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector)
               where TEntity : class
        {
            return repository.AsQueryable().ToDictionary(keySelector);
        }

        public static Dictionary<TKey, TElement> ToDictionary<TEntity, TKey, TElement>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, Func<TEntity, TElement> elementSelector)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionary(keySelector, elementSelector);
        }

        public static Dictionary<TKey, TEntity> ToDictionary<TEntity, TKey>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, IEqualityComparer<TKey> comparer)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionary(keySelector, comparer);
        }

        public static Dictionary<TKey, TElement> ToDictionary<TEntity, TKey, TElement>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, Func<TEntity, TElement> elementSelector, IEqualityComparer<TKey> comparer)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionary(keySelector, elementSelector, comparer);
        }

        #endregion

        #region ToList

        public static List<TEntity> ToList<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().ToList();
        }

        #endregion

        #region Where

        public static IQueryable<TEntity> Where<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().Where(predicate);
        }

        #endregion

        #endregion

        #region Entity Framework

        public static IQueryable<TEntity> AsNoTracking<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().AsNoTracking();
        }

        public static IQueryable<TEntity> Include<TEntity>(this IDbRepository<TEntity> repository, string path)
            where TEntity : class
        {
            return repository.AsQueryable().Include(path);
        }

        public static IQueryable<TEntity> Include<TEntity, TProperty>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TProperty>> path)
            where TEntity : class
        {
            return repository.AsQueryable().Include(path);
        }

        #region Take
        
        public static IQueryable<TEntity> Take<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<int>> countAccessor)
            where TEntity : class
        {
            return repository.AsQueryable().Take(countAccessor);
        }

        #endregion

        #region All

        public static Task<bool> AllAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().AllAsync(predicate);
        }

        public static Task<bool> AllAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AllAsync(predicate, cancellationToken);
        }

        #endregion

        #region Any

        public static Task<bool> AnyAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().AnyAsync();
        }

        public static Task<bool> AnyAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AnyAsync(cancellationToken);
        }

        public static Task<bool> AnyAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().AnyAsync(predicate);
        }

        public static Task<bool> AnyAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AnyAsync(predicate, cancellationToken);
        }

        #endregion

        #region Average

        public static Task<decimal?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<decimal> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<double?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<double> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<float?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<float> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<double?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<double> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<double?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<double> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector);
        }

        public static Task<decimal?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<decimal> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<double?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<double> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<float?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<float> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<double?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<double> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<double?> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        public static Task<double> AverageAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().AverageAsync(selector, cancellationToken);
        }

        #endregion

        #region Contains

        public static Task<bool> ContainsAsync<TEntity>(this IDbRepository<TEntity> repository, TEntity item)
            where TEntity : class
        {
            return repository.AsQueryable().ContainsAsync(item);
        }

        public static Task<bool> ContainsAsync<TEntity>(this IDbRepository<TEntity> repository, TEntity item, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ContainsAsync(item, cancellationToken);
        }

        #endregion

        #region Count

        public static Task<int> CountAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().CountAsync();
        }

        public static Task<int> CountAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().CountAsync(cancellationToken);
        }

        public static Task<int> CountAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().CountAsync(predicate);
        }

        public static Task<int> CountAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().CountAsync(predicate, cancellationToken);
        }

        #endregion

        #region First

        public static Task<TEntity> FirstAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().FirstAsync();
        }

        public static Task<TEntity> FirstAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().FirstAsync(cancellationToken);
        }

        public static Task<TEntity> FirstAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().FirstAsync(predicate);
        }

        public static Task<TEntity> FirstAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().FirstAsync(predicate, cancellationToken);
        }

        #endregion

        #region FirstOrDefault

        public static Task<TEntity> FirstOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().FirstOrDefaultAsync();
        }

        public static Task<TEntity> FirstOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().FirstOrDefaultAsync(cancellationToken);
        }

        public static Task<TEntity> FirstOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().FirstOrDefaultAsync(predicate);
        }

        public static Task<TEntity> FirstOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().FirstOrDefaultAsync(predicate, cancellationToken);
        }

        #endregion

        #region ForEach

        public static Task ForEachAsync<TEntity>(this IDbRepository<TEntity> repository, Action<TEntity> action)
            where TEntity : class
        {
            return repository.AsQueryable().ForEachAsync(action);
        }

        public static Task ForEachAsync<TEntity>(this IDbRepository<TEntity> repository, Action<TEntity> action, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ForEachAsync(action, cancellationToken);
        }

        #endregion

        #region LongCount

        public static Task<long> LongCountAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().LongCountAsync();
        }

        public static Task<long> LongCountAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().LongCountAsync(cancellationToken);
        }

        public static Task<long> LongCountAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().LongCountAsync(predicate);
        }

        public static Task<long> LongCountAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().LongCountAsync(predicate, cancellationToken);
        }

        #endregion

        #region Max

        public static Task<TEntity> MaxAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().MaxAsync();
        }

        public static Task<TEntity> MaxAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().MaxAsync(cancellationToken);
        }

        public static Task<TResult> MaxAsync<TEntity, TResult>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TResult>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().MaxAsync(selector);
        }

        public static Task<TResult> MaxAsync<TEntity, TResult>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TResult>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().MaxAsync(selector, cancellationToken);
        }

        #endregion

        #region Min

        public static Task<TEntity> MinAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().MinAsync();
        }

        public static Task<TEntity> MinAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().MinAsync(cancellationToken);
        }

        public static Task<TResult> MinAsync<TEntity, TResult>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TResult>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().MinAsync(selector);
        }

        public static Task<TResult> MinAsync<TEntity, TResult>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, TResult>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().MinAsync(selector, cancellationToken);
        }

        #endregion

        #region Single

        public static Task<TEntity> SingleAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().SingleAsync();
        }

        public static Task<TEntity> SingleAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SingleAsync(cancellationToken);
        }

        public static Task<TEntity> SingleAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().SingleAsync(predicate);
        }

        public static Task<TEntity> SingleAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SingleAsync(predicate, cancellationToken);
        }

        #endregion

        #region SingleOrDefault

        public static Task<TEntity> SingleOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().SingleOrDefaultAsync();
        }

        public static Task<TEntity> SingleOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SingleOrDefaultAsync(cancellationToken);
        }

        public static Task<TEntity> SingleOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate)
            where TEntity : class
        {
            return repository.AsQueryable().SingleOrDefaultAsync(predicate);
        }

        public static Task<TEntity> SingleOrDefaultAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, bool>> predicate, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SingleOrDefaultAsync(predicate, cancellationToken);
        }

        #region Skip

        #endregion

        public static IQueryable<TEntity> Skip<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<int>> countAccessor)
            where TEntity : class
        {
            return repository.AsQueryable().Skip(countAccessor);
        }

        #endregion

        #region Sum

        public static Task<decimal?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<decimal> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<double?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<double> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<float?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<float> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<int?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<int> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<long?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long?>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<long> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long>> selector)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector);
        }

        public static Task<decimal?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<decimal> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, decimal>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<double?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<double> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, double>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<float?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<float> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, float>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<int?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<int> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, int>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<long?> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long?>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        public static Task<long> SumAsync<TEntity>(this IDbRepository<TEntity> repository, Expression<Func<TEntity, long>> selector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().SumAsync(selector, cancellationToken);
        }

        #endregion

        #region ToArray

        public static Task<TEntity[]> ToArrayAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().ToArrayAsync();
        }

        public static Task<TEntity[]> ToArrayAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ToArrayAsync(cancellationToken);
        }

        #endregion

        #region ToDictionary

        public static Task<Dictionary<TKey, TEntity>> ToDictionaryAsync<TEntity, TKey>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector);
        }

        public static Task<Dictionary<TKey, TEntity>> ToDictionaryAsync<TEntity, TKey>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, cancellationToken);
        }

        public static Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TEntity, TKey, TElement>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, Func<TEntity, TElement> elementSelector)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, elementSelector);
        }

        public static Task<Dictionary<TKey, TEntity>> ToDictionaryAsync<TEntity, TKey>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, IEqualityComparer<TKey> comparer)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, comparer);
        }

        public static Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TEntity, TKey, TElement>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, Func<TEntity, TElement> elementSelector, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, elementSelector, cancellationToken);
        }

        public static Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TEntity, TKey, TElement>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, Func<TEntity, TElement> elementSelector, IEqualityComparer<TKey> comparer)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, elementSelector, comparer);
        }

        public static Task<Dictionary<TKey, TEntity>> ToDictionaryAsync<TEntity, TKey>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, comparer, cancellationToken);
        }

        public static Task<Dictionary<TKey, TElement>> ToDictionaryAsync<TEntity, TKey, TElement>(this IDbRepository<TEntity> repository, Func<TEntity, TKey> keySelector, Func<TEntity, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ToDictionaryAsync(keySelector, elementSelector, comparer, cancellationToken);
        }

        #endregion

        #region ToList

        public static Task<List<TEntity>> ToListAsync<TEntity>(this IDbRepository<TEntity> repository)
            where TEntity : class
        {
            return repository.AsQueryable().ToListAsync();
        }

        public static Task<List<TEntity>> ToListAsync<TEntity>(this IDbRepository<TEntity> repository, CancellationToken cancellationToken)
            where TEntity : class
        {
            return repository.AsQueryable().ToListAsync(cancellationToken);
        }

        #endregion

        #endregion
    }
}
